#![no_std]
#![feature(llvm_asm)]
#![feature(alloc_error_handler)]
#![feature(const_btree_new)]
#![feature(map_first_last)]

#![allow(unused_imports)]


extern crate alloc;
extern crate lazy_static;
extern crate spin;

pub mod object;
pub mod kservice;
pub mod clock;
pub mod components;
pub mod irq;
pub mod rt_extern;
pub mod thread;
pub mod mem;
pub mod scheduler;
pub mod idle;
pub mod timer;
pub mod ipc;

use core::{cell::RefCell, ffi::c_void, panic::PanicInfo, ptr::null};

use alloc::{collections::LinkedList, string::ToString, sync::Arc};

use ipc::{IpcFlag, sem::{RtSem, static_sem}};

use crate::{mem::rt_malloc, rt_extern::idle_wfi, scheduler::*, thread::*};

fn thread1() {
    
    loop {
        println!("this is Thread1! Will sleep.");
        rt_thread_sleep(10);
        println!("Thread1 resume.");
    }
}

fn thread2() {
    
    loop {
        println!("this is Thread2! Will sleep");
        rt_thread_sleep(5);
        println!("Thread2 resume.");
    }
}

fn thread3() {
    println!("thread3, only once!");
}

static mut sem_test: RtSem = static_sem("sem1", 0, 1);
static mut sem_test2: RtSem = static_sem("sem2", 1, 1);
static mut sem_val_test: i32 = 0;

#[no_mangle]
pub fn thread4() {
    for _i in 0..1000 {
        unsafe {
            sem_test2.take(5).unwrap_or(());
            sem_val_test += 1;
            println!("thread4 {}",sem_val_test);
            //rt_thread_sleep(3);
            while let Err(_e) = sem_test.release() {

            }
        }
    }
}

#[no_mangle]
pub fn thread5() {
    for _i in 0..1000 {
        unsafe {
            sem_test.take(5) .unwrap_or(());
            sem_val_test -= 1;
            println!("thread5 {}",sem_val_test);
            //rt_thread_sleep(3);
            while let Err(_e) = sem_test2.release() {};
        }
    }
}




#[no_mangle]
pub fn my_app() {
    // let entry = thread1 as *const c_void;
    // let t1 = rt_thread_create("temp1".to_string(), entry, null(), 4096, 0, 5).unwrap();
    // rt_thread_startup(t1);

    // let entry = thread2 as *const c_void;
    // let t2 = rt_thread_create("temp2".to_string(), entry, null(), 4096, 0, 5).unwrap();
    // rt_thread_startup(t2);

    // let entry = thread3 as *const c_void;
    // let t3 = rt_thread_create("thrad3".to_string(), entry, null(), 4096, 0, 3).unwrap();
    // rt_thread_startup(t3);

    let entry = thread4 as *const c_void;
    let t4 = rt_thread_create("thrad4".to_string(), entry, null(), 4096, 0, 5).unwrap();
    rt_thread_startup(t4);

    let entry = thread5 as *const c_void;
    let t5 = rt_thread_create("thrad5".to_string(), entry, null(), 4096, 0, 5).unwrap();
    rt_thread_startup(t5);
    
    rt_sys_scheduler_start();
    
    panic!("end of app!");
}

#[panic_handler]
fn panic(info:&PanicInfo) -> !{
    println!("{}", info);
    loop{
        unsafe{
            idle_wfi();
        }
    }
}